package com.atguigu.bootredis01.controller;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class GoodController {
    private static final String REDIS_LOCK = "atguiguLock";
    public static final String GOOD_PREFIX = "goods:";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedissonClient redisson;

    @Value("${server.port}")
    private String serverPort;
    //synchronized 不见不散
    //synchronized try.lock过时不候

    /**
     * 这里教学，暂且用最简单的
     */
    @GetMapping("/buy_goods")
    public String buy_Goods() throws Exception {
        String value = UUID.randomUUID() + Thread.currentThread().getName();
        /**
         * 1、用redisson
         */
        RLock redissonLock = redisson.getLock(REDIS_LOCK);
        redissonLock.lock();
        try {
            /**
             * 1、手写
             */
            ////设置key+过期时间分开了，必须要合并成一行具备原子性
            //Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value, 10, TimeUnit.SECONDS);
            //if (!flag) {
            //    return serverPort + "抢锁失败";
            //}

            String result = stringRedisTemplate.opsForValue().get(GOOD_PREFIX + "001");
            int goodsNumber = result == null ? 0 : Integer.parseInt(result);

            if (goodsNumber > 0) {
                int realNumber = goodsNumber - 1;
                stringRedisTemplate.opsForValue().set(GOOD_PREFIX + "001", realNumber + "");
                System.out.println("你已经成功秒杀商品，此时还剩余：" + realNumber + "件" + "\t 服务器端口: " + serverPort);

                return "你已经成功秒杀商品，此时还剩余：" + realNumber + "件" + "\t 服务器端口: " + serverPort;
            } else {
                System.out.println("商品已经售罄/活动结束/调用超时，欢迎下次光临" + "\t 服务器端口: " + serverPort);
            }
            return "商品已经售罄/活动结束/调用超时，欢迎下次光临" + "\t 服务器端口: " + serverPort;
        } finally {

            /**
             * 4、redisson分布式锁
             */
            if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()) {
                redissonLock.unlock();
            }


            /**
             * 1、lua脚本不用工具
             */
            //String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            ////原子删锁
            //Long execute = stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(REDIS_LOCK), value);
            //if (execute==0L) {
            ////    删除失败
            //}else {
            //    //删除成功
            //}

            /**
             * 2、用工具
             */
            //创建jedis客户端
            //Jedis jedis = RedisUtils.getJedis();
            //String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            //
            //try {
            //    Object eval = jedis.eval(script, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
            //    if ("1".equals(eval.toString())) {
            //        //         删除成功逻辑
            //    } else {
            //        //     删除失败逻辑
            //    }
            //} finally {
            //    jedis.close();
            //}

            //判断是自己的锁再删除
            //if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equals(value)) {
            //    stringRedisTemplate.delete(REDIS_LOCK);
            //}

            /**
             * redis事物解决,实际工作中用lua脚本
             */
            //while (true) {
            //    //监控锁
            //    stringRedisTemplate.watch(REDIS_LOCK);
            //    if (stringRedisTemplate.opsForValue().get(REDIS_LOCK).equals(value)){
            //        //开启事物
            //        stringRedisTemplate.setEnableTransactionSupport(true);
            //        stringRedisTemplate.multi();
            //        stringRedisTemplate.delete(REDIS_LOCK);
            //        List<Object> list = stringRedisTemplate.exec();
            //        if (list == null) {
            //        // 执行失败，重试
            //            continue;
            //        }
            //    }
            //    //取消监控锁
            //    stringRedisTemplate.unwatch();
            //    //跳出当前循环
            //    break;
            //}

        }
    }
}


